/**
 * @file database.c
 * @brief Fichier source du module database.
 *
 * @author Rachid Delory, Mamadou Keita, Florian Bernard
 */

/* *********************************************************************

                       Librairies de database                          

********************************************************************* */

#include "database.h"
/**
 * @brief Variable commune à tout le programme. Variable privée
 */
static sqlite3 *pDb = NULL;

/* *********************************************************************

                        Fonctions                                      

********************************************************************* */

void log_Db(void *un, int deux, const char *trois)
{
  printf("Erreur : %s\n", trois);
  (void)un;
  (void)deux;
}

sqlite3 *ouvrir_Db()
{
  const char sNomDB[] = "data/database.db";

  if( pDb ) return pDb;
  if(sqlite3_config(SQLITE_CONFIG_LOG, log_Db, pDb) != SQLITE_OK)
    {
      fprintf(stderr, "ouvrir_Db : Config erreur\n");
    }

  if( SQLITE_OK!=sqlite3_open(sNomDB, &pDb) ){
    fprintf(stderr,"ouvrir_Db : Impossible d'ouvrir la base de donnée \"%s\"", sNomDB);
    sqlite3_close(pDb);
  }
  sqlite3_busy_timeout(pDb, 10000);

  return pDb;
}

void fermer_Db()
{
  if(pDb)
    {
      sqlite3_close(pDb);
      pDb = NULL;
    }
}
int step (const int i){
  switch (i)
    {
    case SQLITE_BUSY:
      fprintf(stderr,"The database file is locked\n");
      break;
    case SQLITE_ERROR:
      fprintf(stderr,"SQL error or missing database\n");
      break;
    case SQLITE_INTERNAL:
      fprintf(stderr,"Internal logic error in SQLite\n");
      break;
    case SQLITE_PERM :
      fprintf(stderr,"Access permission denied\n");
      break;
    case SQLITE_ABORT:
      fprintf(stderr,"Callback routine requested an abort\n");
      break;
    case SQLITE_LOCKED:
      fprintf(stderr,"A table in the database is locked\n");
      break;
    case SQLITE_NOMEM:
      fprintf(stderr,"A malloc() failed\n");
      break;
    case SQLITE_READONLY:
      fprintf(stderr,"Attempt to write a readonly database\n");
      break;
    case SQLITE_INTERRUPT:
      fprintf(stderr,"Operation terminated by sqlite3_interrupt()\n");
      break;
    case SQLITE_IOERR:
      fprintf(stderr,"Some kind of disk I/O error occurred\n");
      break;
    case SQLITE_CORRUPT:
      fprintf(stderr,"The database disk image is malformed\n");
      break;
    case SQLITE_NOTFOUND :
      fprintf(stderr,"Unknown opcode in sqlite3_file_control()\n");
      break;  
    case SQLITE_FULL :
      fprintf(stderr,"Insertion failed because database is full\n");
      break;
    case SQLITE_CANTOPEN :
      fprintf(stderr,"Unable to open the database file\n");
      break;
    case SQLITE_PROTOCOL :
      fprintf(stderr,"Database lock protocol error\n");
      break;
    case SQLITE_EMPTY : 
      fprintf(stderr,"Database is empty\n");
      break;
    case SQLITE_SCHEMA :
      fprintf(stderr,"The database schema changed\n");
      break;
    case SQLITE_TOOBIG :
      fprintf(stderr,"String or BLOB exceeds size limit\n");
      break;
    case SQLITE_CONSTRAINT :
      fprintf(stderr,"Abort due to constraint violation\n");
      break;
    case SQLITE_MISMATCH :
      fprintf(stderr,"Data type mismatch\n");
      break;
    case SQLITE_MISUSE :
      fprintf(stderr,"Library used incorrectly\n");
      break;
    case SQLITE_NOLFS :
      fprintf(stderr,"Uses OS features not supported on host\n");
      break;
    case SQLITE_AUTH :
      fprintf(stderr,"Authorization denied\n");
      break;
    case SQLITE_FORMAT :
      fprintf(stderr,"Auxiliary database format error\n");
      break;
    case SQLITE_RANGE :
      fprintf(stderr,"2nd parameter to sqlite3_bind out of range\n");
      break;
    case SQLITE_NOTADB :
      fprintf(stderr,"File opened that is not a database file\n");
      break;
    case SQLITE_ROW :
      fprintf(stderr,"sqlite3_step() has another row ready\n");
      break;
    case SQLITE_DONE :
      /* 
	 fprintf(stderr,"sqlite3_step() has finished executing\n");
       */
      break;
    case SQLITE_OK :
      /*
	fprintf(stderr,"Succesful result\n");
      */
      break;
    default:
      fprintf(stderr,"Rien trouvé pour l'erreur : %d\n", i);
    }
  return i;
}

int prepare_Db(DataBase *dataBase, const char *requete)
{
  return step(sqlite3_prepare_v2(pDb, requete, strlen(requete), &(dataBase->stmt), NULL));
}

void bindValueInt_Db(DataBase *dataBase, const int nbCol, const int value)
{
  step(sqlite3_bind_int (dataBase->stmt, nbCol, value));
}

void bindValueText_Db(DataBase *dataBase, const int nbCol, const char *value)
{
  if(value)
  step(sqlite3_bind_text (dataBase->stmt, nbCol, value, strlen(value), NULL));
  else
    step(sqlite3_bind_null(dataBase->stmt, nbCol));
}

int execute_Db(DataBase *database)
{
  int ret = sqlite3_step(database->stmt);
  if(ret == SQLITE_DONE)
    return 0;
  if(ret == SQLITE_ROW)
    return 1;
  step(ret);
  return 0;
}

void finalise_Db(DataBase *database)
{
  sqlite3_finalize(database->stmt);
}

int getValueInt_Db(DataBase *dataBase, const int nbCol)
{
  return sqlite3_column_int(dataBase->stmt, nbCol);
}

const char *getValueText_Db(DataBase *dataBase, const int nbCol)
{
  return (const char *)sqlite3_column_text(dataBase->stmt, nbCol);
}  

void regression_Db()
{
  DataBase data;
  ouvrir_Db();
  prepare_Db(&data, "insert into regroupement (ILLUSTRATION, TITRE,TYPE) values( ?, ?, ?)");
  bindValueText_Db(&data, 1, NULL);
  bindValueText_Db(&data, 2, "TEST 1");
  bindValueInt_Db(&data, 3, 1);
  execute_Db(&data);
  finalise_Db(&data);

  /* Recuperation des info */
    prepare_Db(&data, "select rowid, ILLUSTRATION, Titre, TYPE from regroupement");
    execute_Db(&data);  
      do{

	printf("%d\tIllustration : %s\ttitre : %s\t type ; %d\n",getValueInt_Db(&data, 0), getValueText_Db(&data, 1), getValueText_Db(&data, 2), getValueInt_Db(&data, 3));
      }while (execute_Db(&data));
    
  finalise_Db(&data);

  fermer_Db();
}
